package com.wdb007.venus.svc.biz.charge;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;

import org.apache.commons.lang.time.DateFormatUtils;
import org.apache.poi.hssf.usermodel.DVConstraint;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFDataFormat;
import org.apache.poi.hssf.usermodel.HSSFDataValidation;
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.hssf.usermodel.HSSFRichTextString;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.FillPatternType;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.apache.poi.ss.util.CellRangeAddressList;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.wxpay.sdk.WXPayUtil;
import com.wdb.exchange.constant.EventEnum;
import com.wdb007.venus.svc.biz.manager.AlipayClientManager;
import com.wdb007.venus.svc.biz.manager.AlipayTradeStatusEnum;
import com.wdb007.venus.svc.biz.manager.ConfigInfoManager;
import com.wdb007.venus.svc.biz.manager.IntersystemCommunicationManager;
import com.wdb007.venus.svc.biz.manager.WeChatPayClientManager;
import com.wdb007.venus.svc.biz.manager.WeChatTradeStatusEnum;
import com.wdb007.venus.svc.biz.manager.WeChatUtilManager;
import com.wdb007.venus.svc.biz.utils.CommonUtil;
import com.wdb007.venus.svc.biz.utils.DateFormatUtil;
import com.wdb007.venus.svc.biz.utils.DateUtil;
import com.wdb007.venus.svc.biz.utils.MD5Util;
import com.wdb007.venus.svc.biz.utils.PayCommonUtil;
import com.wdb007.venus.svc.biz.utils.UUIDGenerator;
import com.wdb007.venus.svc.biz.utils.XMLUtil;
import com.wdb007.venus.svc.dal.account.dao.AccountCashDAO;
import com.wdb007.venus.svc.dal.account.dao.AccountCashLogDAO;
import com.wdb007.venus.svc.dal.account.model.AccountCashDO;
import com.wdb007.venus.svc.dal.account.model.AccountCashLogDO;
import com.wdb007.venus.svc.dal.book.dao.BookInfoDAO;
import com.wdb007.venus.svc.dal.book.model.BookInfoDO;
import com.wdb007.venus.svc.dal.order.dao.OrderTransDAO;
import com.wdb007.venus.svc.dal.order.model.OrderTransDO;
import com.wdb007.venus.svc.dal.user.dao.UserChargeLogDAO;
import com.wdb007.venus.svc.dal.user.dao.UserInfoDAO;
import com.wdb007.venus.svc.dal.user.dao.UserRefundInfoDAO;
import com.wdb007.venus.svc.dal.user.dao.UserTokenDAO;
import com.wdb007.venus.svc.dal.user.dao.WxUserRelationDAO;
import com.wdb007.venus.svc.dal.user.model.UserBillQueryDO;
import com.wdb007.venus.svc.dal.user.model.UserChargeLogDO;
import com.wdb007.venus.svc.dal.user.model.UserInfoDO;
import com.wdb007.venus.svc.dal.user.model.UserRefundInfoDO;
import com.wdb007.venus.svc.dal.user.model.UserRefundLogDO;
import com.wdb007.venus.svc.dal.user.model.UserTokenDO;
import com.wdb007.venus.svc.dal.user.model.WxUserRelationDO;
import com.wdb007.venus.svc.dal.vip.dao.VipAmountTblDAO;
import com.wdb007.venus.svc.dal.vip.dao.VipMemberDAO;
import com.wdb007.venus.svc.dal.vip.model.VipAmountTblDO;
import com.wdb007.venus.svc.facade.AccountCashService;
import com.wdb007.venus.svc.facade.CouponService;
import com.wdb007.venus.svc.facade.OrderService;
import com.wdb007.venus.svc.facade.UserChargeService;
import com.wdb007.venus.svc.facade.UserCostFlagService;
import com.wdb007.venus.svc.facade.UserPointService;
import com.wdb007.venus.svc.facade.UserService;
import com.wdb007.venus.svc.facade.VipMemberService;
import com.wdb007.venus.svc.facade.WxAPPMessagePushService;
import com.wdb007.venus.svc.facade.account.model.AccountCashDTO;
import com.wdb007.venus.svc.facade.account.model.UserCostFlagDTO;
import com.wdb007.venus.svc.facade.account.model.UserPointDTO;
import com.wdb007.venus.svc.facade.account.model.VipMemberLogDTO;
import com.wdb007.venus.svc.facade.charge.model.CalcPayAmountDTO;
import com.wdb007.venus.svc.facade.charge.model.CalcPayAmountResultDTO;
import com.wdb007.venus.svc.facade.charge.model.ChargeAmountDTO;
import com.wdb007.venus.svc.facade.charge.model.PaymentChargeAmountDTO;
import com.wdb007.venus.svc.facade.charge.model.PaymentVIPCardDTO;
import com.wdb007.venus.svc.facade.charge.model.PaymentVIPCardResultDTO;
import com.wdb007.venus.svc.facade.charge.model.PlaceOrderReqDTO;
import com.wdb007.venus.svc.facade.charge.model.PlaceOrderRspDTO;
import com.wdb007.venus.svc.facade.charge.model.PrepareBuyBookReqDTO;
import com.wdb007.venus.svc.facade.charge.model.PrepareBuyBookResDTO;
import com.wdb007.venus.svc.facade.charge.model.QueryPayStatusDTO;
import com.wdb007.venus.svc.facade.charge.model.RefundPyStatusDTO;
import com.wdb007.venus.svc.facade.charge.model.UserRefundDTO;
import com.wdb007.venus.svc.facade.charge.model.VIPAmountDTO;
import com.wdb007.venus.svc.facade.charge.model.VIPAmountRspDTO;
import com.wdb007.venus.svc.facade.charge.model.WxUserRelationDTO;
import com.wdb007.venus.svc.facade.constant.BizConstants;
import com.wdb007.venus.svc.facade.constant.RspCodeEnum;
import com.wdb007.venus.svc.facade.coupon.model.CouponInfo;
import com.wdb007.venus.svc.facade.exception.BizException;
import com.wdb007.venus.svc.facade.model.VenusSvcResp;
import com.wdb007.venus.svc.facade.order.model.WeChatDto;
import com.wdb007.venus.svc.facade.user.model.UserAccessLogDTO;
import com.wdb007.venus.svc.facade.user.model.UserEntiretyDTO;
import com.wdb007.venus.svc.facade.user.model.UserInfoDTO;

@Service("userChargeService")
public class UserChargeServiceImpl implements UserChargeService {
	private static final Logger logger = LoggerFactory.getLogger(UserChargeServiceImpl.class);
	private static final ObjectMapper mapper = new ObjectMapper();
	@Autowired
	private UserChargeLogDAO userChargeLogDAO;
	
	@Autowired
	private UserTokenDAO userTokenDAO;
	
	@Autowired
	private AlipayClientManager alipayClientManager;
	
	@Autowired
	private WeChatPayClientManager weChatPayClientManager;
	@Autowired
	private WeChatUtilManager weChatUtilManager;
	@Autowired
	private ConfigInfoManager configInfoManager;
	
	@Autowired
	private AccountCashDAO accountCashDAO;
	
	@Autowired
	private AccountCashLogDAO accountCashLogDAO;
	
	@Autowired
	private OrderTransDAO orderTransDAO;
	
	@Autowired
	private UserInfoDAO userInfoDAO;
	
	@Autowired
	private VipAmountTblDAO vipAmountTblDAO;
	@Autowired
	private VipMemberDAO vipMemberDAO;
	
	@Autowired
	private WxUserRelationDAO wxUserRelationDAO;
	
	@Autowired
	private WxAPPMessagePushService wxAPPMessagePushService;
	
	@Autowired
	private UserService userService;
	
	@Autowired
	private AccountCashService accountCashService;
	
	@Autowired
	private UserCostFlagService userCostFlagService;
	
	@Autowired
	private VipMemberService vipMemberService;
	
	@Autowired
	private UserPointService userPointService;
	
	@Autowired
	private UserRefundInfoDAO userRefundInfoDAO;
	
	@Autowired
	private CouponService couponService;
	
	@Autowired
	private OrderService orderService;
	
	@Autowired
	private IntersystemCommunicationManager intersystemCommunicationManager;
	@Override
	public VenusSvcResp<PlaceOrderRspDTO> placeOrder(PlaceOrderReqDTO placeOrder)  throws BizException{
		
		
		//判断用户是否被冻结:
		VenusSvcResp<PlaceOrderRspDTO> svcResp = new VenusSvcResp<PlaceOrderRspDTO>();
		//1.先将数据保存到数据库中
		UserChargeLogDO userChargeLogDO = new UserChargeLogDO();
		userChargeLogDO.setChannel(placeOrder.getChannel());
		String chargeamount = placeOrder.getChargeamount();
		
		Integer vipType = placeOrder.getVip_type();
		if(null == vipType)
			vipType = 0;
		
		String isTest = configInfoManager.getValue("is_test");
		if("1".equals(isTest)) {
			if(0 == placeOrder.getChargetype()) {
				chargeamount = configInfoManager.getValue("test_deposit_amount");
			}else {
				chargeamount = configInfoManager.getValue("test_charge_amount");
			}
		}
		//分解押金和充值金额，数组中第一个是充值金额，第二个是押金金额。
		String[] chargeAmountArr = chargeamount.split("_");
		BigDecimal chargeAmount = null ;
		if(0 == placeOrder.getChargetype()) {
			chargeAmount = new BigDecimal(chargeAmountArr[1]).add(new BigDecimal(chargeAmountArr[0])); 
		}else {
			chargeAmount = new BigDecimal(chargeAmountArr[0]); 
		}
		userChargeLogDO.setChargeAmount(chargeAmount);
		logger.info("当前实际充值金额为\t"+chargeAmount.toString());
		
		userChargeLogDO.setChargeType(placeOrder.getChargetype());
		userChargeLogDO.setCreateTime(DateUtil.now());
		userChargeLogDO.setTradeStatus(BizConstants.USER_CHARGE_STATUS_0);	//初始化
		userChargeLogDO.setUserId(placeOrder.getUserid());
		userChargeLogDO.setVipType(vipType);
		userChargeLogDAO.insert(userChargeLogDO);
		Long id = userChargeLogDO.getId();
		
		String orderStr = "";
		PlaceOrderRspDTO placeOrderRspDTO = new PlaceOrderRspDTO();
		if(null != placeOrder.getChannel() && placeOrder.getChannel() == 0) {//支付宝支付
			//支付宝的订单号
			String outTradeNo = id + "_" + MD5Util.md5(id + "_" + "wdb007");
			userChargeLogDO.setOutTradeNo(outTradeNo);
			userChargeLogDAO.update(userChargeLogDO);
			orderStr = alipayClientManager.generateOrder(outTradeNo, chargeAmount);
			placeOrderRspDTO.setTrade_info(orderStr);
		}else if(null!= placeOrder.getChannel() && placeOrder.getChannel()==1){//微信支付
			String outTradeNo = weChatUtilManager.getRandomNumber();
			userChargeLogDO.setOutTradeNo(outTradeNo);
			userChargeLogDAO.update(userChargeLogDO);
			String chargeAmountStr = ((int)(chargeAmount.doubleValue() * 100))+"";
			Map<String,String> unifiedOrderResponse = weChatPayClientManager.unifiedOrder(outTradeNo,chargeAmountStr, placeOrder.getIp());
			//重新计算签名返回给前段
			String timestamp = (System.currentTimeMillis()+"").substring(0, 10);
			TreeMap<String, String> params =  weChatUtilManager.getPlaceReturn();
			params.put("appid", weChatUtilManager.getWxPayConfig().getAppID());
			params.put("partnerid", weChatUtilManager.getWxPayConfig().getMchID());
			params.put("prepayid", unifiedOrderResponse.get("prepay_id"));
			params.put("noncestr", unifiedOrderResponse.get("nonce_str"));
			params.put("timestamp", timestamp);
			String sign;
			
			try {
				String keyWeChat = configInfoManager.getValue("wechat.key");
				sign = WXPayUtil.generateSignature(params, keyWeChat);
				WeChatDto weChatDto = new WeChatDto();
				weChatDto.setAppId(unifiedOrderResponse.get("appid"));
				weChatDto.setNonceStr(unifiedOrderResponse.get("nonce_str"));
				weChatDto.setPartnerId(unifiedOrderResponse.get("mch_id"));
				weChatDto.setPrepayId(unifiedOrderResponse.get("prepay_id"));
				weChatDto.setSign(sign);
				weChatDto.setTimeStamp(timestamp);
				BeanUtils.copyProperties(weChatDto, placeOrderRspDTO);
			} catch (Exception e) {
				logger.error("微信支付签名错误："+e.toString());
			}
		}
		userChargeLogDO.setTradeStatus(BizConstants.USER_CHARGE_STATUS_1);	//进行中
		userChargeLogDO.setModifyTime(DateUtil.now());
		userChargeLogDAO.update(userChargeLogDO);
		svcResp.setBody(placeOrderRspDTO);
		return svcResp;
	}

	@Override
	public boolean rsaCheckV1(Map<String, String> params)  throws BizException{
		boolean flag = alipayClientManager.rsaCheckV1(params);
		return flag;
	}

	private boolean callBackHandle(Map<String, String> params) throws BizException{
		logger.info("callbackHandler.params: {}", JSON.toJSONString(params));
		boolean bizFlag = true;
		//1.商户需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号
		String out_trade_no = params.get("out_trade_no");
		UserChargeLogDO chargeLogDO = userChargeLogDAO.getByOutTradeNo(out_trade_no);
		if(null == chargeLogDO) {
			logger.info("根据商户订单号[{}]查询出的下单信息是null,接收到的通知信息如下:{}", out_trade_no, JSON.toJSONString(params));
			return false ;
		}
		//**判断该笔订单是否已经完成，属于重复发送的**
		Integer tradeStatus = chargeLogDO.getTradeStatus();
		if(BizConstants.USER_CHARGE_STATUS_2.equals(tradeStatus) || BizConstants.USER_CHARGE_STATUS_6.equals(tradeStatus) || BizConstants.USER_CHARGE_STATUS_5.equals(tradeStatus)) {	//属于交易完成或者退款成功，又重复发送的,不再做后续处理
			return true;
		}
		tradeStatus = BizConstants.USER_CHARGE_STATUS_2 ;
		if(BizConstants.CHARGE_LOG_CHANNEL_0 == chargeLogDO.getChannel()) { //支付宝
			String total_amount_str = params.get("total_amount");
			BigDecimal bd = new BigDecimal(total_amount_str);
			if(AlipayTradeStatusEnum.WAIT_BUYER_PAY.name().equals(params.get("trade_status"))){
				bizFlag = false;
				return bizFlag;
			}
			if(!chargeLogDO.getChargeAmount().equals(bd)) {
				tradeStatus = BizConstants.USER_CHARGE_STATUS_4 ;
				logger.info("根据商品订单号[{}]查询出的订单金额[{}] 与通知的订单金额[{}]不符", out_trade_no, chargeLogDO.getChargeAmount().doubleValue(), total_amount_str);
				bizFlag = false ;
				return bizFlag;
			}
			String app_id = params.get("app_id");
			String local_app_id = alipayClientManager.getAppId();
			if(!local_app_id.equals(app_id)) {
				tradeStatus = BizConstants.USER_CHARGE_STATUS_4 ;
				logger.info("通知的appId[{}] 与 商户本身的appId[{}]不符", app_id, local_app_id);
				bizFlag = false ;
				return bizFlag;
			}
			//如果是交易关闭的话
			if(AlipayTradeStatusEnum.TRADE_CLOSED.name().equals(params.get("trade_status"))) {
				tradeStatus = BizConstants.USER_CHARGE_STATUS_5 ;
				bizFlag = true;
			}
			chargeLogDO.setTradeNo(params.get("trade_no"));
		}else {	//微信
			String total_amount_str = params.get("total_fee");
			BigDecimal bd = new BigDecimal(total_amount_str);
			if(chargeLogDO.getChargeAmount().multiply(new BigDecimal("100")).compareTo(bd) != 0) {
				tradeStatus = BizConstants.USER_CHARGE_STATUS_4;
				logger.info("根据商品订单号[{}]查询出的订单金额[{}] 与通知的订单金额[{}]不符", out_trade_no,
						chargeLogDO.getChargeAmount().multiply(new BigDecimal("100")).doubleValue(), total_amount_str);
				bizFlag = false;
				return bizFlag;
			}
			String app_id = params.get("appid");
			String local_app_id = configInfoManager.getValue("wechat.appid");
			String wx_app_id = configInfoManager.getValue("wxapp.appid");
			if (!(local_app_id.equals(app_id) || wx_app_id.equals(app_id))) {
				tradeStatus = BizConstants.USER_CHARGE_STATUS_4;
				logger.info("通知的appId[{}] 与 商户本身的appId[{}]或者[{}]不符", app_id, local_app_id, wx_app_id);
				bizFlag = false;
				return bizFlag;
			}
			SimpleDateFormat sdf =   new SimpleDateFormat("yyyyMMddHHmmss");
			try {
				chargeLogDO.setModifyTime(sdf.parse(params.get("time_end")));
			} catch (ParseException e) {
				logger.error("支付结果通知返回的xml中时间转化错误，xml中的时间为:"+params.get("time_end"));
				return false;
			}
			//如果是交易关闭的话
			if(AlipayTradeStatusEnum.TRADE_CLOSED.name().equals(params.get("trade_status"))) {
				tradeStatus = BizConstants.USER_CHARGE_STATUS_5 ;
				bizFlag = true;
			}
			chargeLogDO.setTradeNo(params.get("transaction_id"));
		}
		chargeLogDO.setNotifyInfo(JSON.toJSONString(params));
		chargeLogDO.setTradeStatus(tradeStatus);
		chargeLogDO.setModifyTime(new Date());
		userChargeLogDAO.update(chargeLogDO);
		
		saveChargeInfo(chargeLogDO);
		return bizFlag;
	}
	
	/**
	 * 保存充值信息
	 * @param chargeLogDO
	 * @throws BizException
	 */
	private void saveChargeInfo(UserChargeLogDO chargeLogDO) throws BizException{
		
		Integer vipType = chargeLogDO.getVipType();
		BigDecimal chargeAmount = chargeLogDO.getChargeAmount();
		String isTest = configInfoManager.getValue("is_test");
		if("1".equals(isTest)){
			chargeAmount = chargeLogDO.getExAmount();
		}
		BigDecimal cashAmount = chargeAmount;
		//保存余额信息
		if(0 == vipType) {
			if(!ObjectUtils.isEmpty(chargeLogDO.getCouponId())) {
				CouponInfo couponInfo = couponService.getCouponById(chargeLogDO.getCouponId());
				if(couponInfo != null) {
					String couponType = couponInfo.getCoupon_type();
					if("1".equals(couponType) || "2".equals(couponType)) { //满减券
						cashAmount = cashAmount.add(new BigDecimal(couponInfo.getCoupon_cash()));
					}else if("4".equals(couponType)){	//绘本优惠券
						// 如果是绘本优惠券的话,则支付金额为0;
					}
				}
			}
			
			
			AccountCashDTO accountCash = new AccountCashDTO();
			accountCash.setUserId(chargeLogDO.getUserId());
			accountCash.setOperType(BizConstants.ACCOUNT_CASH_OPER_TYPE_10);
			accountCash.setChangeAmount(cashAmount);
			if(BizConstants.CHARGE_LOG_CHANNEL_0 == chargeLogDO.getChannel()) {
				accountCash.setChargeType(BizConstants.ACCOUNT_CASH_CHARGE_TYPE_20);
			}else {
				accountCash.setChargeType(BizConstants.ACCOUNT_CASH_CHARGE_TYPE_10);
			}
			accountCash.setOrderId(chargeLogDO.getId());
			//押金充值
			if(BizConstants.USER_CHARGE_LOG_CHARGE_TYPE_0.equals(chargeLogDO.getChargeType())) {
				accountCash.setDepositFlag(true);
			}
			if(new BigDecimal("0.00").compareTo(cashAmount) != 0) {
				accountCashService.updateAccountCash(accountCash);
			}
		}else if(null != chargeLogDO.getAcAmount() && 0 != chargeLogDO.getVipType()) { //说明是使用余额来进行购买月卡
			AccountCashDTO accountCash = new AccountCashDTO();
			accountCash.setUserId(chargeLogDO.getUserId());
			accountCash.setOperType(BizConstants.ACCOUNT_CASH_OPER_TYPE_20);
			accountCash.setChangeAmount(new BigDecimal(chargeLogDO.getAcAmount()).divide(new BigDecimal("100")).setScale(2, RoundingMode.HALF_UP));
			accountCash.setChargeType(BizConstants.ACCOUNT_CASH_CHARGE_TYPE_51);
			accountCash.setOrderId(chargeLogDO.getId());
			accountCashService.updateAccountCash(accountCash);
		}
		
		//FIXME 购买图书余额计算
		Long orderTransId = chargeLogDO.getOrderTransId();
		if(null != orderTransId) {
			AccountCashDTO accountCash = new AccountCashDTO();
			accountCash.setUserId(chargeLogDO.getUserId());
			accountCash.setOperType(BizConstants.ACCOUNT_CASH_OPER_TYPE_20);
			accountCash.setChangeAmount(new BigDecimal(chargeLogDO.getAcAmount()).divide(new BigDecimal("100")).setScale(2, RoundingMode.HALF_UP).add(cashAmount));
			accountCash.setChargeType(BizConstants.ACCOUNT_CASH_CHARGE_TYPE_52);
			accountCash.setOrderId(chargeLogDO.getId());
			accountCashService.updateAccountCash(accountCash);
			
			//更新order_trans表
			orderService.updateByBuyBook(orderTransId);
		}
		
		//保存用户扣费标准信息
		UserCostFlagDTO ucfDTO = new UserCostFlagDTO();
		ucfDTO.setUserId(chargeLogDO.getUserId());
		//余额充值
		if(BizConstants.USER_CHARGE_LOG_CHARGE_TYPE_1.equals(chargeLogDO.getChargeType())) {
			if(0 == vipType) {
				ucfDTO.setFlag(1);
				ucfDTO.setPrice(new BigDecimal(configInfoManager.getValue("cost_per_book_per_day")));
				ucfDTO.setRemainder(cashAmount);
			}else if(1 == vipType) {
				ucfDTO.setFlag(3);
				ucfDTO.setPrice(new BigDecimal("0.00"));
				ucfDTO.setRemainder(chargeAmount);
			}else if(2 == vipType) {
				ucfDTO.setFlag(4);
				ucfDTO.setPrice(new BigDecimal("0.00"));
				ucfDTO.setRemainder(chargeAmount);
			}
		}
		userCostFlagService.saveUserCostFlag(ucfDTO);
		
		//保存用户vip信息
		if(0 != vipType) {
			VipMemberLogDTO vmlDTO = new VipMemberLogDTO();
			vmlDTO.setUserId(chargeLogDO.getUserId());
			vmlDTO.setChargeType(10);
			vmlDTO.setVipType(vipType);
			vipMemberService.saveVipMember(vmlDTO);
		}
		
		//更新用户信息
		UserInfoDO userInfo = userInfoDAO.get(chargeLogDO.getUserId());
		if(1 == userInfo.getStatus() && BizConstants.USER_CHARGE_LOG_CHARGE_TYPE_0.equals(chargeLogDO.getChargeType())) {
			userInfo.setModifyTime(new Date());
			userInfo.setStatus(0);
			userInfoDAO.update(userInfo);
		}
		
		//增加用户积分信息
		UserPointDTO userPointDTO = new UserPointDTO();
		userPointDTO.setUserId(chargeLogDO.getUserId());
		if(BizConstants.USER_CHARGE_LOG_CHARGE_TYPE_0.equals(chargeLogDO.getChargeType())) {
			userPointDTO.setChangeType(49);
			userPointDTO.setChangeValue(50);
		}else {
			userPointDTO.setChangeType(47);
			userPointDTO.setChangeValue((int)chargeAmount.doubleValue());
		}
		userPointService.updateUserPoint(userPointDTO);
		
		//更新优惠券信息
		String couponId = chargeLogDO.getCouponId();
		if(!ObjectUtils.isEmpty(couponId)) {
			couponService.updateCoupon(couponId, BizConstants.COUPON_EVENT_USED, chargeLogDO.getId());
		}
	}

	@Override
	public boolean bizHandle(Map<String, String> params)  throws BizException{
		logger.info("bizHandle start----");
		return callBackHandle(params);
	}
	@Override
	public boolean weChatNotify(Map<String, String> params)  throws BizException{
		logger.info("weChatNotify start----");
		return callBackHandle(params);
	}

	/**
	 * 成功充值之后的对象组装
	 * @param chargeLogDO
	 * @return
	 * @throws BizException 
	 */
	private QueryPayStatusDTO createSuccessPayStatus(UserChargeLogDO chargeLogDO) throws BizException {
		QueryPayStatusDTO queryPayStatus = new QueryPayStatusDTO();
		queryPayStatus.setStatus(1);
		queryPayStatus.setCash(chargeLogDO.getChargeAmount());
		BigDecimal chargeAmount = accountCashService.getChargeAmount(chargeLogDO.getId());
		if(null != chargeAmount) {
			queryPayStatus.setCash(chargeAmount);
		}
		queryPayStatus.setDetail("支付成功");
		if(0 == chargeLogDO.getVipType()) {
			if(!ObjectUtils.isEmpty(chargeLogDO.getCouponId())) {
				CouponInfo couponInfo = couponService.getCouponById(chargeLogDO.getCouponId());
				if(couponInfo != null) {
					String couponType = couponInfo.getCoupon_type();
					if("1".equals(couponType) || "2".equals(couponType)) { //满减券
						chargeAmount = chargeAmount.add(new BigDecimal(couponInfo.getCoupon_cash()));
						queryPayStatus.setCash(chargeAmount);
					}
					
				}
			}
		}else if(1 == chargeLogDO.getVipType()) {
			Date expire = vipMemberDAO.getExpireDate(chargeLogDO.getUserId());
			queryPayStatus.setVip_type("月卡");
			queryPayStatus.setVip_content(DateFormatUtil.formatDate(expire));
			
		}else if(2 == chargeLogDO.getVipType()){
			Date expire = vipMemberDAO.getExpireDate(chargeLogDO.getUserId());
			queryPayStatus.setVip_type("年卡");
			queryPayStatus.setVip_content(DateFormatUtil.formatDate(expire));;
		}
		if(0 != chargeLogDO.getVipType()) {
			if(chargeLogDO.getChargeAmount().compareTo(new BigDecimal("0.00")) != 0) {
				queryPayStatus.setExtra_amount(chargeLogDO.getChargeAmount().setScale(2).toString());
				queryPayStatus.setCash_amount(new BigDecimal(chargeLogDO.getAcAmount()).divide(new BigDecimal("100")).setScale(2, RoundingMode.HALF_UP).toString());
				BigDecimal bd = new BigDecimal(queryPayStatus.getExtra_amount()).add(new BigDecimal(queryPayStatus.getCash_amount()));
				queryPayStatus.setPay_amount(bd.setScale(2, RoundingMode.HALF_UP).toString());
			}
		}
		return queryPayStatus;
	}
	@Override
	public QueryPayStatusDTO queryPayStatus(long userId) throws BizException{
		UserChargeLogDO chargeLogDO = userChargeLogDAO.getByUserId(userId);//根据UserId查询最新的未付款账单
		if(chargeLogDO == null) {
			throw new BizException(RspCodeEnum.OBJ_NOT_FOUND.setRspMessage("订单"));
		}
		String outTradeNo = chargeLogDO.getOutTradeNo();//是否添加对null的处理
		QueryPayStatusDTO queryPayStatus = new QueryPayStatusDTO();
		Integer tradeStatus = chargeLogDO.getTradeStatus();
		queryPayStatus.setVip_type("");
		if(BizConstants.USER_CHARGE_STATUS_2 == tradeStatus) {
			return createSuccessPayStatus(chargeLogDO);
		}else if(BizConstants.USER_CHARGE_STATUS_5 == tradeStatus 
				|| BizConstants.USER_CHARGE_STATUS_6 == tradeStatus
				|| BizConstants.USER_CHARGE_STATUS_7 == tradeStatus 
				|| BizConstants.USER_CHARGE_STATUS_3 == tradeStatus 
				) {
			queryPayStatus.setStatus(2);
			queryPayStatus.setDetail("交易关闭");
			return queryPayStatus;
		}
		
		//------------调用查询接口---------------------------------------------
		Integer channel = chargeLogDO.getChannel();
		String tradeNo = "";
		String tradeInfo="";
		if(BizConstants.CHARGE_LOG_CHANNEL_0 == channel) { //支付宝支付
			//支付宝
			Map<String, String> queryResult = alipayClientManager.queryOrderStatus(outTradeNo);
			String ali_trade_status = queryResult.get("tradeStatus");
			tradeNo = queryResult.get("tradeNo");
			tradeInfo = queryResult.get("tradeInfo");
			//交易完成，不可退款
			if(AlipayTradeStatusEnum.TRADE_FINISHED.name().equals(ali_trade_status)) {
				tradeStatus = BizConstants.USER_CHARGE_STATUS_2;
			//交易创建，等待买家付款
			}else if(AlipayTradeStatusEnum.WAIT_BUYER_PAY.name().equals(ali_trade_status)) {
				tradeStatus = BizConstants.USER_CHARGE_STATUS_1;
			//交易支付成功
			}else if(AlipayTradeStatusEnum.TRADE_SUCCESS.name().equals(ali_trade_status)) {
				tradeStatus = BizConstants.USER_CHARGE_STATUS_2;
			}else{
			//未付款交易超时关闭，或支付完成后全额退款	
				tradeStatus = BizConstants.USER_CHARGE_STATUS_4;
			}
		}else {	//微信支付
			Map<String, String> orderResponseMaps = weChatPayClientManager.queryOrderStatus(outTradeNo);
			if(orderResponseMaps==null) {
				queryPayStatus.setStatus(4);
				queryPayStatus.setDetail("支付失败");
				return queryPayStatus;
			}
			String resultCode = orderResponseMaps.get("result_code");
			if (null != resultCode && "SUCCESS".equals(resultCode.trim())) {
				String tradeState = orderResponseMaps.get("trade_state");
				logger.info("tradeState: {}" , tradeState);
				if (WeChatTradeStatusEnum.SUCCESS.name().equals(tradeState.trim())) {
					tradeStatus = BizConstants.USER_CHARGE_STATUS_2;
				}else if (WeChatTradeStatusEnum.REFUND.name().equals(tradeState.trim())) {
					queryPayStatus.setStatus(2);
					queryPayStatus.setDetail("转入退款");
					tradeStatus = BizConstants.USER_CHARGE_STATUS_3;
				} else if (WeChatTradeStatusEnum.NOTPAY.name().equals(tradeState.trim())) {
					queryPayStatus.setStatus(0);
					queryPayStatus.setDetail("未支付");
					tradeStatus = BizConstants.USER_CHARGE_STATUS_0;
				} else if (WeChatTradeStatusEnum.CLOSED.name().equals(tradeState.trim())) {
					queryPayStatus.setStatus(2);
					queryPayStatus.setDetail("已关闭");
					tradeStatus = BizConstants.USER_CHARGE_STATUS_5;
				} else if (WeChatTradeStatusEnum.REVOKED.name().equals(tradeState.trim())) {
					queryPayStatus.setStatus(2);
					queryPayStatus.setDetail("已撤销");
					tradeStatus = BizConstants.USER_CHARGE_STATUS_3;
				} else if (WeChatTradeStatusEnum.USERPAYING.name().equals(tradeState.trim())) {
					queryPayStatus.setStatus(3);
					queryPayStatus.setDetail("用户支付中");
					tradeStatus = BizConstants.USER_CHARGE_STATUS_1;
				} else if (WeChatTradeStatusEnum.PAYERROR.name().equals(tradeState.trim())) {
					queryPayStatus.setStatus(4);
					queryPayStatus.setDetail("支付失败");
					tradeStatus = BizConstants.USER_CHARGE_STATUS_4;
				}
			}else {
				String errCodeDes = orderResponseMaps.get("err_code_des");
				queryPayStatus.setStatus(4);
				queryPayStatus.setDetail(errCodeDes.trim());
				tradeStatus = BizConstants.USER_CHARGE_STATUS_4;
			}
			String jsonfromMap = null;
			try {
				jsonfromMap =  mapper.writeValueAsString(orderResponseMaps);
				chargeLogDO.setNotifyInfo(jsonfromMap);
			} catch (JsonProcessingException e) {
				logger.error("map转json数据出错："+e);
				chargeLogDO.setNotifyInfo("map转json数据出错："+e);
			} 
		}
		chargeLogDO.setTradeStatus(tradeStatus);
		chargeLogDO.setModifyTime(DateUtil.now());
		chargeLogDO.setTradeNo(tradeNo);
		chargeLogDO.setNotifyInfo(tradeInfo);
		userChargeLogDAO.update(chargeLogDO);
		if(BizConstants.USER_CHARGE_STATUS_2 == tradeStatus) {
			saveChargeInfo(chargeLogDO);
			return createSuccessPayStatus(chargeLogDO);
		}else if(BizConstants.USER_CHARGE_STATUS_5 == tradeStatus) {
			queryPayStatus.setStatus(2);
			queryPayStatus.setDetail("交易关闭");
			return queryPayStatus;
		}else {
			queryPayStatus.setStatus(3);
			queryPayStatus.setDetail("交易进行中");
			return queryPayStatus;
		}
	}
	
	@Override
	public RefundPyStatusDTO refund(String outTradeNo) throws BizException {
		
		RefundPyStatusDTO refundPyStatusDTO = new RefundPyStatusDTO();
		UserChargeLogDO userChargeLog = userChargeLogDAO.getByOutTradeNo(outTradeNo);
		if(userChargeLog == null) {
			throw new BizException(RspCodeEnum.OBJ_NOT_FOUND);
		}
		String auditStatus = userChargeLog.getAuditStatus();
		if(null == auditStatus || "".equals(auditStatus)) {
			throw new BizException(RspCodeEnum.REFUND_AUDIT_STATUS_INVALID);
		}
		if("1".equals(auditStatus)) {
			throw new BizException(RspCodeEnum.REFUND_AUDDIT_NOT_PASSED);
		}
		if("2".equals(auditStatus)) {
			throw new BizException(RspCodeEnum.REFUND_AUDDIT_REFUSED);
		}
		if("4".equals(auditStatus)) {
			throw new BizException(RspCodeEnum.REFUND_SUCCESS);
		}
		if(BizConstants.USER_CHARGE_STATUS_7 == userChargeLog.getTradeStatus()) {
			throw new BizException(RspCodeEnum.REFUND_SUCCESS);
		}
		Long userId = userChargeLog.getUserId();
		AccountCashDO accountCashDO = accountCashDAO.getByUserid(userId);
		
		BigDecimal refundPrice = new BigDecimal(configInfoManager.getValue("refund_deposit_amount"));
		Integer channel = userChargeLog.getChannel();
		String current = System.currentTimeMillis()+"";
		AccountCashLogDO accountCashLogDO = new AccountCashLogDO();
		accountCashLogDO.setAccountCashId(accountCashDO.getId());
		try {
			if(BizConstants.CHARGE_LOG_CHANNEL_0 == channel) {	//支付宝
				String refund_amount = refundPrice.doubleValue()+"";
				alipayClientManager.refund(outTradeNo, refund_amount, current);
				accountCashDO.setDepositAmount(new BigDecimal("0.00"));
				accountCashDO.setModifyTime(new Date());
				accountCashDAO.update(accountCashDO);
				accountCashLogDO.setOperType(30);
				accountCashLogDO.setChargeType(20);// 10-微信;20-支付宝;30-系统赠送;40-书格扣款;50-租书扣款
				accountCashLogDO.setChangeAmount(refundPrice);// 变动金额
				accountCashLogDO.setCreateTime(new Date());
				accountCashLogDAO.insert(accountCashLogDO);// 记录流水信息

				userChargeLog.setTradeStatus(BizConstants.USER_CHARGE_STATUS_6);
				userChargeLog.setAuditStatus("4");
			} else { // 微信
				String refund_amount = (int)(refundPrice.doubleValue() * 100) + "";
//				String refund_amount = "1";
				String total_amount = (int)(userChargeLog.getChargeAmount().doubleValue() * 100) +"";//冲押金时候订单的总金额
				Map<String, String> refurnResponseMaps = weChatPayClientManager.refundOrder(outTradeNo, refund_amount, current,total_amount);
				if(null==refurnResponseMaps) {
					userChargeLog.setAuditStatus("5");
					userChargeLog.setTradeStatus(BizConstants.USER_CHARGE_STATUS_7);
					userChargeLog.setModifyTime(new Date());
					userChargeLogDAO.update(userChargeLog);
					throw new BizException(RspCodeEnum.REFUND_AUDDIT_FAILED);
				}
				// Node returnCode = element.selectSingleNode("return_code");
				String resultCode = refurnResponseMaps.get("result_code");
				if (null != resultCode && "SUCCESS".equals(resultCode.trim())) {
					refundPyStatusDTO.setStatus(1);
					refundPyStatusDTO.setDetail("退款成功");
					accountCashDO.setDepositAmount(new BigDecimal("0.00"));
					accountCashDO.setModifyTime(new Date());
					accountCashDAO.update(accountCashDO);
					accountCashLogDO.setChargeType(10);// 10-微信;20-支付宝;30-系统赠送;40-书格扣款;50-租书扣款
					accountCashLogDO.setChangeAmount(refundPrice);// 变动金额
					accountCashLogDO.setOperType(30);
					accountCashLogDO.setCreateTime(new Date());
					accountCashLogDAO.insert(accountCashLogDO);// 记录流水信息
					userChargeLog.setTradeStatus(BizConstants.USER_CHARGE_STATUS_6);
					userChargeLog.setAuditStatus("4");
					
					//退款成功发送消息
					wxAPPMessagePushService.sendBackDepositSuccessNotice(userId);
					intersystemCommunicationManager.publishEvent(userId, EventEnum.CANCEL_DEPOSIT);
				} else {
					userChargeLog.setAuditStatus("5");
					userChargeLog.setTradeStatus(BizConstants.USER_CHARGE_STATUS_7);
					userChargeLog.setModifyTime(new Date());
					userChargeLogDAO.update(userChargeLog);
					throw new BizException(RspCodeEnum.REFUND_AUDDIT_FAILED);
				}
			}
		} catch (Exception e) {
			logger.error("退款失败", e);
			userChargeLog.setAuditStatus("5");
			userChargeLog.setTradeStatus(BizConstants.USER_CHARGE_STATUS_7);
			userChargeLog.setModifyTime(new Date());
			userChargeLogDAO.update(userChargeLog);
			throw new BizException(RspCodeEnum.REFUND_AUDDIT_FAILED);
		}
		userChargeLog.setModifyTime(DateUtil.now());
		userChargeLogDAO.update(userChargeLog);
		return refundPyStatusDTO;
	}
	
	
	@Override
	public RefundPyStatusDTO refund(Long userid) throws BizException{
		logger.info("refund=====userId:[{}]", userid);
		RefundPyStatusDTO refundPyStatusDTO = new RefundPyStatusDTO();
		//1.校验余额是否大于0
		AccountCashDO accountCashDO = accountCashDAO.getByUserid(userid);
		BigDecimal originalCashAmount = accountCashDO.getCashAmount();//客户当前余额
		if(null == originalCashAmount || originalCashAmount.compareTo(new BigDecimal("0.00")) < 0) {
			throw new BizException(RspCodeEnum.REFUND_CASH_IS_LT_ZERO);
		}
		//2.校验是否有在借的图书
		int count = orderTransDAO.getBorrowingCount(userid);
		if(count > 0) {
			throw new BizException(RspCodeEnum.REFUND_CAN_NOT);
		}
		
		//提前准备流水相关
		AccountCashLogDO accountCashLogDO = new AccountCashLogDO();
		accountCashLogDO.setAccountCashId(accountCashDO.getId());
		accountCashLogDO.setOperType(BizConstants.ACCOUNT_CASH_OPER_TYPE_30);//10 充值  20 扣款
		accountCashLogDO.setCreateTime(new Date());
		//获取客户当前关于押金相关信息
		UserChargeLogDO chargeLog = userChargeLogDAO.getDepositByUserId(userid);
		if(chargeLog == null) {
			throw new BizException(RspCodeEnum.OBJ_NOT_FOUND.setRspMessage("订单"));
		}
		if(BizConstants.USER_CHARGE_STATUS_7 == chargeLog.getTradeStatus() || BizConstants.USER_CHARGE_STATUS_6 == chargeLog.getTradeStatus() ) {
			throw new BizException(RspCodeEnum.REFUND_SUCCESS);
		}
//		BigDecimal price = chargeLog.getChargeAmount();//退款订单的金额
		BigDecimal refundPrice = null ;
		String isTest = configInfoManager.getValue("is_test");
		if("1".equals(isTest)){
			refundPrice = new BigDecimal(configInfoManager.getValue("test_refund_deposit_amount"));
		}else{
			refundPrice = new BigDecimal(configInfoManager.getValue("refund_deposit_amount"));
		}
		String outTradeNo  = chargeLog.getOutTradeNo();
		Integer channel = chargeLog.getChannel();
		String current = System.currentTimeMillis()+"";
		if(BizConstants.CHARGE_LOG_CHANNEL_0 == channel) {	//支付宝
			String refund_amount = refundPrice.doubleValue()+"";
			alipayClientManager.refund(outTradeNo, refund_amount, current);
			
			accountCashDO.setDepositAmount(new BigDecimal("0.00"));
			accountCashDO.setModifyTime(new Date());
			accountCashDAO.update(accountCashDO);
			accountCashLogDO.setChargeType(20);// 10-微信;20-支付宝;30-系统赠送;40-书格扣款;50-租书扣款
			accountCashLogDO.setChangeAmount(refundPrice);// 变动金额
			accountCashLogDAO.insert(accountCashLogDO);// 记录流水信息
			chargeLog.setTradeStatus(BizConstants.USER_CHARGE_STATUS_6);
			chargeLog.setAuditStatus("4");
			refundPyStatusDTO.setStatus(105);
			refundPyStatusDTO.setDetail("退款成功");
			wxAPPMessagePushService.sendBackDepositSuccessNotice(userid);
			intersystemCommunicationManager.publishEvent(userid, EventEnum.CANCEL_DEPOSIT);
		} else { // 微信
			String refund_amount = (int)(refundPrice.doubleValue() * 100) + "";
			String total_amount = (int)(chargeLog.getChargeAmount().doubleValue() * 100) +"";//冲押金时候订单的总金额
			Map<String, String> refurnResponseMaps = weChatPayClientManager.refundOrder(outTradeNo, refund_amount, current,total_amount);
			if(null==refurnResponseMaps) {
				refundPyStatusDTO.setStatus(0);
				refundPyStatusDTO.setDetail("退款失败");
				return refundPyStatusDTO;
			}
			String resultCode = refurnResponseMaps.get("result_code");
			if (null != resultCode && "SUCCESS".equals(resultCode.trim())) {
				refundPyStatusDTO.setStatus(1);
				refundPyStatusDTO.setDetail("退款成功");
				accountCashDO.setDepositAmount(new BigDecimal("0.00"));
				accountCashDO.setModifyTime(new Date());
				accountCashDAO.update(accountCashDO);
				accountCashLogDO.setChargeType(10);// 10-微信;20-支付宝;30-系统赠送;40-书格扣款;50-租书扣款
				accountCashLogDO.setChangeAmount(refundPrice);// 变动金额
				accountCashLogDAO.insert(accountCashLogDO);// 记录流水信息

				chargeLog.setTradeStatus(BizConstants.USER_CHARGE_STATUS_6);
				chargeLog.setAuditStatus("4");
				refundPyStatusDTO.setStatus(105);
				refundPyStatusDTO.setDetail("退款成功");
				
				wxAPPMessagePushService.sendBackDepositSuccessNotice(userid);
				intersystemCommunicationManager.publishEvent(userid, EventEnum.CANCEL_DEPOSIT);
			} else {
				refundPyStatusDTO.setStatus(0);
				refundPyStatusDTO.setDetail("退款失败");
				chargeLog.setTradeStatus(BizConstants.USER_CHARGE_STATUS_7);
			}
		}
		chargeLog.setModifyTime(DateUtil.now());
		userChargeLogDAO.update(chargeLog);
		logger.info("refund's response: {}", JSON.toJSONString(refundPyStatusDTO));
		
		return refundPyStatusDTO;
	}

	@Override
	public void downloadBill(String billDate) throws BizException {
		
		String os = System.getenv("OS");
		String bill_path = "";
		if("Windows_NT".equalsIgnoreCase(os)) {
			bill_path = configInfoManager.getValue("bill_download_path_windows");
		}else {
			bill_path = configInfoManager.getValue("bill_download_path");
		}
		String dateShort = billDate.replaceAll("-", "");
		File dir = mkdir(bill_path, dateShort);
		String aliFileName = "ali_bill_" + dateShort + ".csv";
		String aliFilePath = dir.getAbsolutePath() +  File.separator + aliFileName;
		alipayClientManager.downloadBill(billDate, aliFilePath);
		
		String weixinFileName = "wx_bill_" + dateShort +".xls";
		String weixinFilePath = dir.getAbsolutePath() +  File.separator + weixinFileName;
		weChatPayClientManager.downloadBill(dateShort, "ALL", weixinFilePath);
		
		//下载数据库中的数据
		UserBillQueryDO query = new UserBillQueryDO();
		query.setStartTime(billDate + " 00:00:00");
		query.setEndTime(billDate + " 23:59:59");
		List<UserChargeLogDO> list = userChargeLogDAO.listByDate(query);
		
		String[] headers = new String[] {
				"商品订单号" , "订单号" , "支付渠道", "充值类型", "充值金额", "交易状态"
		};
		String title = "用户交易导出流水";
		String dbFileName = "db_bill_" + dateShort + ".xls";
		String dbFielPath =  dir.getAbsolutePath() +  File.separator + dbFileName;
		try {
			FileOutputStream outputStream = new FileOutputStream(new File(dbFielPath));
			export(title, headers, list, outputStream);
		} catch (FileNotFoundException e) {
			logger.error("用户交易导出流水失败", e);
		}
	}
	
	private File mkdir(String path, String child) {
		File parentFile = new File(path);
		if(!parentFile.exists() || !parentFile.isDirectory()) {
			parentFile.mkdirs();
		}
		File file = new File(parentFile, child);
		if(!file.exists() || !file.isDirectory()) {
			file.mkdirs();
		}
		return file;
	}
	
	//定时导出数据
	public void exportReadyForRefund() {
		
		exportReadyForRefund(null);
		
	}
	
	public void exportReadyForRefund(Date date) {
		if(null == date)
			date = new Date();
		String os = System.getenv("OS");
		String bill_path = "";
		if("Windows_NT".equalsIgnoreCase(os)) {
			bill_path = configInfoManager.getValue("bill_download_path_windows");
		}else {
			bill_path = configInfoManager.getValue("bill_download_path");
		}
		DateFormat df = new SimpleDateFormat("yyyyMMdd");
		String dateShort = df.format(new Date());
		File dir = new File(bill_path);
		if(!dir.exists() || !dir.isDirectory()) {
			dir.mkdirs();
		}
		
		String refund = "ready_refund_" + dateShort +".xls";
		
		List<UserRefundLogDO> refundList = userChargeLogDAO.getRefundList();
		if(CollectionUtils.isEmpty(refundList)) {
			logger.info("当日没有退款的申请记录，不做后续处理...");
		}
		
		FileOutputStream outputStream;
		try {
			outputStream = new FileOutputStream(new File(dir, refund));
			String title = "退款申请流水";
			String[] headers = {
				"流水号", "用户手机号", "用户名称", "押金", "余额", "充值渠道", "支付订单号", "退款状态", "退款申请时间"	
			};
			exportRefund(title, headers, refundList, outputStream);
		} catch (Exception e) {
			logger.error("创建退款申请流水文件失败", e);
		}
	}
	
	private void exportRefund(String title, String[] headers, List<UserRefundLogDO> refundList,
			FileOutputStream outputStream) throws Exception{
		
		//1.声明一个工作簿
		HSSFWorkbook workbook = new HSSFWorkbook();
		
		//2.生成一个表格
		HSSFSheet sheet = workbook.createSheet(title);
		
		//3.设置表格默认列宽度为30个字节
		sheet.setDefaultColumnWidth(15);
		
		//4.生成一个样式
		HSSFCellStyle style = workbook.createCellStyle();
		// 设置这些样式
		style.setFillForegroundColor(new HSSFColor.GREY_25_PERCENT().getIndex());
		style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
		style.setBorderBottom(BorderStyle.THICK);
		style.setBorderLeft(BorderStyle.THICK);
		style.setBorderRight(BorderStyle.THICK);
		style.setBorderTop(BorderStyle.THICK);
		style.setAlignment(HorizontalAlignment.CENTER);
		style.setVerticalAlignment(VerticalAlignment.CENTER);
		// 生成一个字体
		HSSFFont font = workbook.createFont();
		font.setColor(HSSFColor.VIOLET.index);
		font.setFontHeightInPoints((short) 12);
		font.setBold(true);
		// 把字体应用到当前的样式
		style.setFont(font);
		// 生成并设置另一个样式
		HSSFCellStyle style2 = workbook.createCellStyle();
		style2.setFillForegroundColor(HSSFColor.LIGHT_YELLOW.index);
		style2.setAlignment(HorizontalAlignment.CENTER);
		style2.setBorderBottom(BorderStyle.THIN);
		style2.setFillPattern(FillPatternType.SOLID_FOREGROUND);
		style2.setBorderLeft(BorderStyle.THIN);
		style2.setBorderRight(BorderStyle.THIN);
		style2.setBorderTop(BorderStyle.THIN);
		style2.setVerticalAlignment(VerticalAlignment.CENTER);
		// 生成另一个字体
		HSSFFont font2 = workbook.createFont();
		font2.setFontHeightInPoints((short) 12);
		font2.setBold(false);
		// 把字体应用到当前的样式
		style2.setFont(font2);
		
		HSSFCellStyle style3 = workbook.createCellStyle();
		style3.setFillForegroundColor(HSSFColor.LIGHT_YELLOW.index);
		style3.setAlignment(HorizontalAlignment.LEFT);
		style3.setBorderBottom(BorderStyle.THIN);
		style3.setFillPattern(FillPatternType.SOLID_FOREGROUND);
		style3.setBorderLeft(BorderStyle.THIN);
		style3.setBorderRight(BorderStyle.THIN);
		style3.setBorderTop(BorderStyle.THIN);
		style3.setVerticalAlignment(VerticalAlignment.CENTER);
		style3.setFont(font2);
		
		String[] status = new String[] { "退款待审核", "审核拒绝", "退款审核同意"};
		CellRangeAddressList regions = new CellRangeAddressList(1, refundList.size()+1, 7, 7);
		DVConstraint constraint = DVConstraint.createExplicitListConstraint(status);
		//绑定
		HSSFDataValidation dataValidation = new HSSFDataValidation(regions, constraint);
        sheet.addValidationData(dataValidation);
		//5.产生表格标题行
		HSSFRow row = sheet.createRow(0);
		row.setHeight((short)600);
		for (short i = 0; i < headers.length; i++) {
		   HSSFCell cell = row.createCell(i);
		   cell.setCellStyle(style);
		   HSSFRichTextString text = new HSSFRichTextString(headers[i]);
		   cell.setCellValue(text);
		}
		
		//6.遍历集合数据，产生数据行
		int index = 0;
		HSSFCellStyle numberCellStyle = workbook.createCellStyle();
		HSSFDataFormat format = workbook.createDataFormat();
		numberCellStyle.setFillForegroundColor(HSSFColor.LIGHT_YELLOW.index);
		numberCellStyle.setAlignment(HorizontalAlignment.RIGHT);
		numberCellStyle.setBorderBottom(BorderStyle.THIN);
		numberCellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
		numberCellStyle.setBorderLeft(BorderStyle.THIN);
		numberCellStyle.setBorderRight(BorderStyle.THIN);
		numberCellStyle.setBorderTop(BorderStyle.THIN);
		numberCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
		numberCellStyle.setFont(font2);
		numberCellStyle.setDataFormat(format.getFormat("#,##0.00"));
		sheet.setColumnWidth(6, 255*60);
		
		for(UserRefundLogDO log : refundList) {
			row = sheet.createRow(++index);
			row.setHeight((short)500);
			HSSFCell cell0 = row.createCell(0);
			cell0.setCellStyle(style3);
			cell0.setCellValue(log.getId());
			HSSFCell cell1 = row.createCell(1);
			cell1.setCellStyle(style2);
			cell1.setCellValue(log.getMobile());
			
			HSSFCell cell2 = row.createCell(2);
			cell2.setCellStyle(style2);
			cell2.setCellValue(log.getUsername());
			
			//添加带有formatting的Number对象 
			
			HSSFCell cell3 = row.createCell(3);
			cell3.setCellStyle(numberCellStyle);
			cell3.setCellValue(log.getDepositAmount().setScale(2, RoundingMode.HALF_EVEN).doubleValue());
			
			HSSFCell cell4 = row.createCell(4);
			cell4.setCellStyle(numberCellStyle);
			cell4.setCellValue(log.getCashAmount().setScale(2, RoundingMode.HALF_EVEN).doubleValue());
			
			HSSFCell cell5 = row.createCell(5);
			cell5.setCellStyle(style2);
			Integer channel = log.getChannel();
			if(BizConstants.CHARGE_LOG_CHANNEL_0 == channel) {
				cell5.setCellValue("支付宝");
			}else {
				cell5.setCellValue("微信");
			}
			
			HSSFCell cell6 = row.createCell(6);
			cell6.setCellStyle(style2);
			cell6.setCellValue(log.getTradeNo());
			
			HSSFCell cell7 = row.createCell(7);
			cell7.setCellStyle(style2);
			String auditStatus = log.getAuditStatus();
			if("1".equals(auditStatus)) {
				cell7.setCellValue("退款待审核");
			}else if("2".equals(auditStatus)) {
				cell7.setCellValue("审核拒绝");
			}else {
				cell7.setCellValue("退款审核同意");
			}
			
			HSSFCell cell8 = row.createCell(8);
			cell8.setCellStyle(style2);
			cell8.setCellValue(DateFormatUtils.format(log.getAuditDate(), "yyyy-MM-dd"));
		}
		
		try {
			workbook.write(outputStream);
		} catch (IOException e) {
			logger.error("导出数据库数据异常", e);
		}finally {
			try {
				workbook.close();
			} catch (IOException e) {
			}
		}
	}

	public void export(String title, String[] headers, List<UserChargeLogDO> list, OutputStream output){
		// 声明一个工作薄
		HSSFWorkbook workbook = new HSSFWorkbook();
		// 生成一个表格
		HSSFSheet sheet = workbook.createSheet(title);
		// 设置表格默认列宽度为15个字节
		sheet.setDefaultColumnWidth((short) 15);
		// 生成一个样式
		HSSFCellStyle style = workbook.createCellStyle();
		// 设置这些样式
		style.setFillForegroundColor(HSSFColor.SKY_BLUE.index);
		style.setAlignment(HorizontalAlignment.CENTER);
		style.setBorderBottom(BorderStyle.MEDIUM);
		style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
		style.setBorderLeft(BorderStyle.MEDIUM);
		style.setBorderRight(BorderStyle.MEDIUM);
		style.setBorderTop(BorderStyle.MEDIUM);
		// 生成一个字体
		HSSFFont font = workbook.createFont();
		font.setColor(HSSFColor.VIOLET.index);
		font.setFontHeightInPoints((short) 12);
		font.setBold(true);
		// 把字体应用到当前的样式
		style.setFont(font);
		// 生成并设置另一个样式
		HSSFCellStyle style2 = workbook.createCellStyle();
		style2.setFillForegroundColor(HSSFColor.LIGHT_YELLOW.index);
		style.setAlignment(HorizontalAlignment.CENTER);
		style.setBorderBottom(BorderStyle.MEDIUM);
		style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
		style.setBorderLeft(BorderStyle.MEDIUM);
		style.setBorderRight(BorderStyle.MEDIUM);
		style.setBorderTop(BorderStyle.MEDIUM);
		style2.setVerticalAlignment(VerticalAlignment.CENTER);
		// 生成另一个字体
		HSSFFont font2 = workbook.createFont();
		font2.setBold(false);
		// 把字体应用到当前的样式
		style2.setFont(font2);
		//产生表格标题行
		HSSFRow row = sheet.createRow(0);
		for (short i = 0; i < headers.length; i++) {
		   HSSFCell cell = row.createCell(i);
		   cell.setCellStyle(style);
		   HSSFRichTextString text = new HSSFRichTextString(headers[i]);
		   cell.setCellValue(text);
		}
		//遍历集合数据，产生数据行
		int index = 0;
		for(UserChargeLogDO userChargeLogDO : list) {
			index++;
			row = sheet.createRow(index);
			HSSFCell cell0 = row.createCell(0);
			cell0.setCellValue(userChargeLogDO.getOutTradeNo());
			HSSFCell cell1 = row.createCell(1);
			cell1.setCellValue(userChargeLogDO.getTradeNo());
			Integer channel = userChargeLogDO.getChannel();
			HSSFCell cell2 = row.createCell(2);
			if(BizConstants.CHARGE_LOG_CHANNEL_0 == channel) {
				cell2.setCellValue("支付宝");
			}else {
				cell2.setCellValue("微信");
			}
			Integer chargeType = userChargeLogDO.getChargeType();
			HSSFCell cell3 = row.createCell(3);
			if(BizConstants.USER_CHARGE_LOG_CHARGE_TYPE_0 == chargeType) {
				cell3.setCellValue("押金充值");
			}else {
				cell3.setCellValue("余额充值");
			}
			
			BigDecimal chargeAmount = userChargeLogDO.getChargeAmount();
			HSSFCell cell4 = row.createCell(4);
			cell4.setCellValue(chargeAmount.doubleValue());
			
			Integer tradeStatus = userChargeLogDO.getTradeStatus();
			HSSFCell cell5 = row.createCell(5);
			if(BizConstants.USER_CHARGE_STATUS_2 == tradeStatus) {
				cell5.setCellValue("交易成功");
			}else if(BizConstants.USER_CHARGE_STATUS_3 == tradeStatus) {
				cell5.setCellValue("交易取消");
			}else if(BizConstants.USER_CHARGE_STATUS_4 == tradeStatus) {
				cell5.setCellValue("交易失败");
			}else if(BizConstants.USER_CHARGE_STATUS_5 == tradeStatus) {
				cell5.setCellValue("交易关闭");
			}else if(BizConstants.USER_CHARGE_STATUS_6 == tradeStatus) {
				cell5.setCellValue("退款成功");
			}else if(BizConstants.USER_CHARGE_STATUS_7 == tradeStatus) {
				cell5.setCellValue("退款成功");
			}
		}
		
		try {
			workbook.write(output);
		} catch (IOException e) {
			logger.error("导出数据库数据异常", e);
		}finally {
			try {
				workbook.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
	@Override
	public RefundPyStatusDTO refundSubmit(Long userid) throws BizException {
		RefundPyStatusDTO refundPyStatusDTO = new RefundPyStatusDTO();
//		try {
			String auto_refund_switch = configInfoManager.getValue("auto_refund_switch");
			if("1".equals(auto_refund_switch)){
				return refund(userid);
			}
		
			//1.校验余额是否大于0
			AccountCashDO accountCashDO = accountCashDAO.getByUserid(userid);
			BigDecimal originalCashAmount = accountCashDO.getCashAmount();//客户当前余额
			if(null == originalCashAmount || originalCashAmount.compareTo(new BigDecimal("0.00")) < 0) {
				throw new BizException(RspCodeEnum.REFUND_CASH_IS_LT_ZERO);
			}
			//2.校验是否有在借的图书
			int count = orderTransDAO.getBorrowingCount(userid);
			if(count > 0) {
				throw new BizException(RspCodeEnum.REFUND_CAN_NOT);
			}
			//查询客户当前押金状态
			UserChargeLogDO chargeLog = userChargeLogDAO.getDepositByUserId(userid);
			if(chargeLog==null || 2 != chargeLog.getTradeStatus()) {
				throw new BizException(RspCodeEnum.REFUND_NO_DEPOSIT);
			}else if("1".equals(chargeLog.getAuditStatus())) {
				throw new BizException(RspCodeEnum.REFUND_HAS_SUBMITTED);
			}else if("2".equals(chargeLog.getAuditStatus())) {
				throw new BizException(RspCodeEnum.REFUND_IS_REFUSED);
			}else if("3".equals(chargeLog.getAuditStatus())) {
				throw new BizException(RspCodeEnum.REFUND_AUDIT_SUCCESS);
			}
			//更改用户充值押金记录的状态为审核
			//冻结该用户，使之不能在进行借还书操作。
			UserInfoDO userInfo = userInfoDAO.get(userid);
			userInfo.setModifyTime(new Date());
			userInfo.setStatus(1);
			userInfoDAO.update(userInfo);
			userChargeLogDAO.updateAudit(userid);
			refundPyStatusDTO.setStatus(1);
			refundPyStatusDTO.setDetail("退款申请成功");
//		}catch (Exception e) {
//			refundPyStatusDTO.setStatus(0);
//			refundPyStatusDTO.setDetail("退款申请失败");
//		}
		return refundPyStatusDTO;
	}

	@Override
	public Map<String, String> getOpenId(String code, String userid) throws BizException {

		String wxappRequestUrl = configInfoManager.getValue("wxapp.request_url");
		String wxAppId = configInfoManager.getValue("wxapp.appid");
		String wxSecret = configInfoManager.getValue("wxapp.secret");
		wxappRequestUrl = wxappRequestUrl.replace("APPID", wxAppId).replace("SECRET", wxSecret).replace("JSCODE", code);
		logger.info("初始requestUrl:{}", wxappRequestUrl);
		JSONObject jsonObject = CommonUtil.httpsRequest(wxappRequestUrl, "GET", null);
		logger.info("getOpenId微信小程序端返回 json:{}", jsonObject);
		Map<String, String> result = new HashMap<String, String>();

		String openId = (String) jsonObject.get("openid");
		String unionid = (String) jsonObject.get("unionid");
		if (null == openId) {
			throw new BizException(RspCodeEnum.WX_GET_OPENID_FAILED);
		}
		result.put("openid", openId);
		result.put("session_key", (String) jsonObject.get("session_key"));
		result.put("unionid", unionid);

		// 保存用户信息
		WxUserRelationDTO relation = new WxUserRelationDTO();
		relation.setAppId(wxAppId);
		relation.setOpenid(openId);
		relation.setUnionid(unionid);
		if(!ObjectUtils.isEmpty(userid)) {
			relation.setUserId(Long.valueOf(userid));
		}
		saveWxUserInfo(relation);

		return result;
	}
	
	/**
	 * 
	 * @param code wxLogin的code
	 * @param appid 微信appid
	 * @return
	 * @throws BizException
	 */
	public Map<String, Object> getUserinfoByWxCode(String code,UserAccessLogDTO accessLog) throws BizException{
		String wxappRequestUrl = configInfoManager.getValue("wxapp.request_url");
		String wxAppId = configInfoManager.getValue("wxapp.appid");
		String wxSecret = configInfoManager.getValue("wxapp.secret");
		wxappRequestUrl = wxappRequestUrl.replace("APPID", wxAppId).replace("SECRET", wxSecret).replace("JSCODE", code);
		logger.info("初始requestUrl:{}", wxappRequestUrl);
		JSONObject jsonObject = CommonUtil.httpsRequest(wxappRequestUrl, "GET", null);
		logger.info("getOpenId微信小程序端返回 json:{}", jsonObject);
		Map<String, String> result = new HashMap<String, String>();

		String openId = (String) jsonObject.get("openid");
		if (null == openId) {
			throw new BizException(RspCodeEnum.WX_GET_OPENID_FAILED);
		}
		String unionid = null;
		if(!ObjectUtils.isEmpty(jsonObject.get("unionid"))) {
			unionid = (String) jsonObject.get("unionid");
		}
		String sessionKey = jsonObject.getString("session_key");
		WxUserRelationDO wxUserRelationDO = new WxUserRelationDO();
		wxUserRelationDO.setAppId(wxAppId);
		wxUserRelationDO.setOpenid(openId);
		wxUserRelationDO.setUnionid(unionid);
		wxUserRelationDO.setSessionKey(sessionKey);
		//存储wx_user_relation
		return  saveWxUserRelation(wxUserRelationDO, accessLog);
	}
	/**
	 * 1.3.0新增接口
	 * @param wxUserRelationDO
	 * @return
	 */
	public synchronized Map<String, Object> saveWxUserRelation(WxUserRelationDO wxUserRelationDO,
			UserAccessLogDTO accessLog) throws BizException {
		Map<String, Object> result = new HashMap<>();
		//判断是否存在当前openid和appid的记录
		WxUserRelationDO query = new WxUserRelationDO();
		query.setAppId(wxUserRelationDO.getAppId());
		query.setOpenid(wxUserRelationDO.getOpenid());
		List<WxUserRelationDO> list = wxUserRelationDAO.listByCondition(query);
		//不存在，新增，并返回
		String token = "";
		if(CollectionUtils.isEmpty(list)) {
			wxUserRelationDO.setId(UUIDGenerator.getUUID());
			wxUserRelationDO.setCreateTime(new Date());
			wxUserRelationDAO.insert(wxUserRelationDO);
			token = wxUserRelationDO.getId();
		}else {
			//存在，update
			WxUserRelationDO oldInfo = list.get(0);
			Long userId = oldInfo.getUserId();
			if(!ObjectUtils.isEmpty(userId)) {
				//返回userinfo信息
				//根据userid查询phone
				UserInfoDTO userinfo = userService.get(userId);
				String mobile = userinfo.getMobileNo();
				if(!ObjectUtils.isEmpty(mobile)) {
					VenusSvcResp<UserEntiretyDTO> userloginInfo = userService.loginWithoutVerifaction(null, null, mobile, accessLog, null);
					token = userloginInfo.getBody().getUsertoken();
					result.put("userInfo", userloginInfo.getBody());
					result.put("mobile", mobile);
				}else {
					token =  oldInfo.getId();
				}
				//根据userid
			}else {
				//不存在userid说明未绑定
				token = oldInfo.getId();
			}
			//更新wx_user_relation
			WxUserRelationDO record = new WxUserRelationDO();
			record.setId(oldInfo.getId());
			record.setSessionKey(wxUserRelationDO.getSessionKey());
			record.setUserId(wxUserRelationDO.getUserId());
			record.setUnionid(wxUserRelationDO.getUnionid());
			wxUserRelationDAO.updateById(record);
		}
		result.put("usertoken", token);
		return result;
	}

	/**
	 * 根据token查询sessionkey信息
	 * @param id
	 * @return
	 */
	public String getSessionKey(String id) {
		WxUserRelationDO record = new WxUserRelationDO();
		record.setId(id);
		record = wxUserRelationDAO.getInfoById(record);
		if(ObjectUtils.isEmpty(record)) return null;
		String sessionKey =record.getSessionKey();
		
		return sessionKey;
	}
	
	@Override
	public PlaceOrderRspDTO payment(PlaceOrderReqDTO placeOrder) throws BizException {
		//1.先将数据保存到数据库中
		UserChargeLogDO userChargeLogDO = new UserChargeLogDO();
		userChargeLogDO.setChannel(BizConstants.CHARGE_LOG_CHANNEL_1);
		String isTest = configInfoManager.getValue("is_test");
		String chargeamount = placeOrder.getChargeamount();
		if("1".equals(isTest)) {
			if(0 == placeOrder.getChargetype()) {
				chargeamount = configInfoManager.getValue("test_deposit_amount");
			}else {
				chargeamount = configInfoManager.getValue("test_charge_amount");
			}
		}
		
		String[] chargeAmountArr = chargeamount.split("_");
		BigDecimal chargeAmount = null ;
		if(0 == placeOrder.getChargetype()) {
			chargeAmount = new BigDecimal(chargeAmountArr[1]).add(new BigDecimal(chargeAmountArr[0])); 
		}else {
			chargeAmount = new BigDecimal(chargeAmountArr[0]); 
		}
		userChargeLogDO.setChargeAmount(chargeAmount);
		logger.info("当前实际充值金额为\t"+chargeAmount.toString());
		if(null != placeOrder.getVip_type()) {
			userChargeLogDO.setVipType(placeOrder.getVip_type());
		}else {
			userChargeLogDO.setVipType(0);
		}
		userChargeLogDO.setChargeType(placeOrder.getChargetype());
		userChargeLogDO.setCreateTime(DateUtil.now());
		userChargeLogDO.setTradeStatus(BizConstants.USER_CHARGE_STATUS_0);	//初始化
		userChargeLogDO.setUserId(placeOrder.getUserid());
		userChargeLogDAO.insert(userChargeLogDO);
//		Long id = userChargeLogDO.getId();
		//单纯考虑微信充值
		String outTradeNo = weChatUtilManager.getRandomNumber();
		userChargeLogDO.setOutTradeNo(outTradeNo);
		userChargeLogDAO.update(userChargeLogDO);
		String total_fee = (int)(chargeAmount.doubleValue()*100) +"";
		String wxAppId = configInfoManager.getValue("wxapp.appid");
		String mch_id =  configInfoManager.getValue("wxapp.merchant_id");
		String notifyUrl = configInfoManager.getValue("wxapp.notify_url");
		String merchant_key = configInfoManager.getValue("wxapp.merchant_key");
		
		//获取OPENID 
		String openid = wxUserRelationDAO.getOpenIdByUser(placeOrder.getUserid());
		String prepayId = payment("微信小程序-支付", outTradeNo, openid, total_fee, wxAppId, mch_id, notifyUrl, merchant_key, placeOrder.getIp());
		logger.info("openid:{},统一下单返回:{}",openid,prepayId);
		
		SortedMap<Object, Object> signParams = new TreeMap<Object, Object>();
		String timeStamp = PayCommonUtil.create_timestamp();
		String nonceStr = PayCommonUtil.create_nonce_str();
		signParams.put("appId", wxAppId);
		signParams.put("nonceStr", nonceStr);
		signParams.put("package", "prepay_id=" + prepayId);
		signParams.put("timeStamp", timeStamp);
		signParams.put("signType", "MD5");
		// 生成支付签名，要采用URLENCODER的原始值进行MD5算法！
		String sign = PayCommonUtil.createSign(signParams, merchant_key);
		PlaceOrderRspDTO dto = new PlaceOrderRspDTO();
		dto.setAppId(wxAppId);
		dto.setNonceStr(nonceStr);
		dto.setPkg("prepay_id=" + prepayId);
		dto.setPrepayId(prepayId);
		dto.setSign(sign);
		dto.setSignType("MD5");
		dto.setTimeStamp(timeStamp);
		return dto;
	}
	
	private String payment(String body, String out_trade_no, String openid, String total_fee, 
			String appid, String mch_id, String notify_url, String apiKey, String ip) {
		SortedMap<Object, Object> parameters = new TreeMap<Object, Object>();
		
		parameters.put("appid", appid);
		parameters.put("mch_id", mch_id);
		parameters.put("nonce_str", PayCommonUtil.CreateNoncestr());
		parameters.put("body", body);
		parameters.put("out_trade_no", out_trade_no);
		parameters.put("total_fee", total_fee);
		parameters.put("spbill_create_ip", ip);
		parameters.put("notify_url", notify_url);
		parameters.put("trade_type", "JSAPI");
		parameters.put("openid", openid);
		
		String sign = PayCommonUtil.createSign(parameters, apiKey);
		parameters.put("sign", sign);
		
		String requestXML = PayCommonUtil.getRequestXml(parameters);
		String orderUrl = configInfoManager.getValue("wxapp.order_url");
		logger.info("requestXML: {}", requestXML);
		String result = CommonUtil.httpsRequest(orderUrl, "POST", requestXML, "1");
		logger.info("微信支付下单请求返回:{}",result);
		Map<String, String> map = new HashMap<String, String>();
		try {
			map = XMLUtil.doXMLParse(result);
		} catch (Exception e) {
		}  // 解析微信返回的信息，以Map形式存储便于取值
		
		return map.get("prepay_id").toString();
	}

	@Override
	public VIPAmountRspDTO getVIPAmountList(Long userid) throws BizException {
		
		//1.获取VIP会员充值列表
		List<VipAmountTblDO> list = vipAmountTblDAO.list();
		if(CollectionUtils.isEmpty(list))
			throw new BizException(RspCodeEnum.QUERY_LIST_IS_NULL);
		VIPAmountRspDTO dto = new VIPAmountRspDTO();
		AccountCashDO accountCash = accountCashDAO.getByUserid(userid);
		BigDecimal ca = accountCash.getCashAmount();
		for(VipAmountTblDO vat : list) {
			VIPAmountDTO vipAmountDTO = new VIPAmountDTO();
			vipAmountDTO.setVip_amount(vat.getVipAmount());
			vipAmountDTO.setVip_content(vat.getVipName());
			vipAmountDTO.setVip_type(vat.getVipType()+"");
			vipAmountDTO.setVip_imgurl(configInfoManager.getImgUrlPrefix() + vat.getVipImgurl());
			//FIXME 根据月卡或者年卡以及金额 从用户优惠券中获取最好的一个优惠券信息
			CouponInfo couponInfo = couponService.getCoupon(vat.getVipType()+"", userid, vat.getVipAmount().setScale(0).toString());
			BigDecimal payAmountBd = null ;
			if(null != couponInfo) {
				vipAmountDTO.setCoupon_id(couponInfo.getCoupon_id());
				vipAmountDTO.setCoupon_type(couponInfo.getCoupon_desc());
				if(!ObjectUtils.isEmpty(couponInfo.getCoupon_cash())) {
					Integer discount = Integer.valueOf(couponInfo.getCoupon_cash());
					BigDecimal discountBd = new BigDecimal(couponInfo.getCoupon_cash());
					if(0 == discount) {
						vipAmountDTO.setCoupon_discount("免费");
					}else if(discount % 10 == 0) {
						vipAmountDTO.setCoupon_discount(discount / 10 + "折");
					}else {
						vipAmountDTO.setCoupon_discount(discountBd.divide(new BigDecimal("10")).setScale(1).toString() + "折");
					}
					//计算优惠金额:
					BigDecimal couponBd = new BigDecimal(100-discount).multiply(vat.getVipAmount()).divide(new BigDecimal("100.00")).setScale(2, RoundingMode.HALF_UP);
					vipAmountDTO.setCoupon_amount("减" + couponBd.toString());
					payAmountBd = vat.getVipAmount().subtract(couponBd).setScale(2, RoundingMode.HALF_UP);
				}
			}else {
				payAmountBd = vat.getVipAmount();
			}
			vipAmountDTO.setPay_amount(payAmountBd.toString());
			if(new BigDecimal("0.00").compareTo(ca) > 0) {
				vipAmountDTO.setExtra_amount(payAmountBd.toString());
			}else if(payAmountBd.compareTo(ca) > 0) {
				vipAmountDTO.setExtra_amount(payAmountBd.subtract(ca).setScale(2).toString());
			}else {
				vipAmountDTO.setExtra_amount("0.00");
			}
			dto.getList().add(vipAmountDTO);
		}
		//2.获取VIP用户最后过期时间
		Date expireDate = vipMemberDAO.getExpireDate(userid);
		if(expireDate != null) {
			DateFormat df = new SimpleDateFormat("yyyy年MM月dd日");
			String ed = df.format(expireDate);
			dto.setTip_content("您的VIP特权将在"+ ed +"内截止，请点击下列按钮为您的特权续费获取更多的特权时间");
		}
		//3.获取用户优惠券信息:  FIXME
		if(new BigDecimal("0.00").compareTo(ca) > 0) {	//如果为负，则需要支付月卡全部的金额
			dto.setCash_flag(0);
		}else {				
			dto.setCash_flag(1);
		}
		dto.setCash_amount(ca.setScale(2).toString());
		return dto;
	}

	@Override
	public synchronized void saveWxUserInfo(WxUserRelationDTO relation) throws BizException {
		logger.info("saveWxUserInfo imp relation unionid:{},openid:{},userid:{}",relation.getUnionid(),relation.getOpenid(),relation.getUserId());
		//1.根据openid 和appid查询是否有数据
		if(ObjectUtils.isEmpty(relation.getOpenid())) {
			throw new BizException(RspCodeEnum.CODE_SYS_ERROR);
		}
		// 用户id和unionid之间的关联
		logger.info("saveWxUserInfo,update unionid:{},userid:{}", relation.getUnionid(), relation.getUserId());
		userService.setUserinfoUnionidNull(relation, relation.getUserId());
		
		WxUserRelationDO query = new WxUserRelationDO();
		query.setAppId(relation.getAppId());
		query.setOpenid(relation.getOpenid());
		String unionid = relation.getUnionid();
		if("null".equals(unionid)) unionid = null;
		List<WxUserRelationDO> list = wxUserRelationDAO.listByCondition(query);
		if(CollectionUtils.isEmpty(list)) {//2.如果没有则新增
			WxUserRelationDO record = new WxUserRelationDO();
			BeanUtils.copyProperties(relation, record);
			synchronized(relation) {//防止同时插入多次
				record.setCreateTime(new Date());
				record.setId(UUIDGenerator.getUUID());
				wxUserRelationDAO.insert(record);
			}
			
		}else {//3.如果有则更新
			WxUserRelationDO result = list.get(0);
			if(!ObjectUtils.isEmpty(relation.getNickName())) {
				result.setNickName(relation.getNickName());
			}
			if(!ObjectUtils.isEmpty(relation.getAvatarUrl())) {
				result.setAvatarUrl(relation.getAvatarUrl());
			}
			if(!ObjectUtils.isEmpty(relation.getUserId())) {
				result.setUserId(relation.getUserId());
			}
			if(!ObjectUtils.isEmpty(relation.getUnionid()) && !"undefined".equals(relation.getUnionid())) {
				result.setUnionid(relation.getUnionid());
			}
			result.setUserId(relation.getUserId());
			result.setModifyTime(new Date());
			wxUserRelationDAO.update(result);//更新当前用户
		}
		
	}
	
	public WxUserRelationDTO getWxInfoByUserid(Long userid, String appid){
		WxUserRelationDO query = new WxUserRelationDO();
		query.setAppId(appid);
		query.setUserId(userid);
		List<WxUserRelationDO> dtos = wxUserRelationDAO.listByCondition(query);
		
		WxUserRelationDTO result = new WxUserRelationDTO();
		if(!CollectionUtils.isEmpty(dtos)) {
			BeanUtils.copyProperties(dtos.get(0), result);
		}
		
		return result;
		
		
		
	}

	@Override
	public List<UserInfoDTO> getUserinfoByUnionid(String unionid, Long userid, String mobileNo) {
		UserInfoDO userinfoDo = new UserInfoDO();
		List<UserInfoDTO>  userInfoDTOs = new ArrayList<>();
		userinfoDo.setUnionid(unionid);
		userinfoDo.setId(userid);
		userinfoDo.setMobileNo(mobileNo);
		List<UserInfoDO> userinfoDos = userInfoDAO.getUserinfoByUnionid(userinfoDo);
		if(!ObjectUtils.isEmpty(userinfoDos)) {
			logger.info("getUserinfoByUnionid userinfoDos{}",userinfoDos.size());

			for(UserInfoDO u:userinfoDos) {
				UserInfoDTO userinfo = new UserInfoDTO();
				BeanUtils.copyProperties(u,userinfo);
				userInfoDTOs.add(userinfo);
			}
		}
		
		return userInfoDTOs;
	}

	@Override
	public CalcPayAmountResultDTO calcPayAmount(CalcPayAmountDTO calcPayAmount) throws BizException {
		
		CalcPayAmountResultDTO result = new CalcPayAmountResultDTO();
		
		BigDecimal amount = new BigDecimal(calcPayAmount.getAmount());
		BigDecimal couponAmount = new BigDecimal("0.00");
		//1.余额
		BigDecimal cash_amount = new BigDecimal("0.00");
		if(!ObjectUtils.isEmpty(calcPayAmount.getCash_amount())) {
			cash_amount = new BigDecimal(calcPayAmount.getCash_amount());
		}
		if(cash_amount.compareTo(new BigDecimal("0.00")) < 0) {
			cash_amount = new BigDecimal("0.00");
		}
		//2.优惠券
		String couponId = calcPayAmount.getCoupon_id();
		BigDecimal payAmount = amount ;
		if(!ObjectUtils.isEmpty(couponId)) {
			CouponInfo couponInfo = couponService.getCouponById(couponId);
			if(null != couponInfo) {
				//FIXME 需要校验用户选择的优惠券是否是他本人的，以及优惠券的优惠金额、优惠券的类型是否匹配
				result.setCoupon_id(couponId);
				result.setCoupon_type(couponInfo.getCoupon_desc());
				if(!ObjectUtils.isEmpty(couponInfo.getCoupon_cash())) {
					Integer discount = Integer.valueOf(couponInfo.getCoupon_cash());
					BigDecimal discountBd = new BigDecimal(couponInfo.getCoupon_cash());
					if("1".equals(couponInfo.getCoupon_type())) {//满减券
						couponAmount =  discountBd;
						result.setCoupon_amount("减" + couponAmount.toString());
						result.setCoupon_discount("满" + couponInfo.getCoupon_condition()+"元减"+couponInfo.getCoupon_cash()+"元");
						payAmount = amount.subtract(couponAmount).setScale(2, RoundingMode.HALF_UP);
					}else if("2".equals(couponInfo.getCoupon_type())) { //满赠卷
						couponAmount =  discountBd;
						result.setCoupon_amount("减" + couponAmount.toString());
						result.setCoupon_discount("满" + couponInfo.getCoupon_condition()+"元赠"+couponInfo.getCoupon_cash()+"元");
					}else if("3".equals(couponInfo.getCoupon_type())){	//折扣券
						if(0 == discount) {
							result.setCoupon_discount("免费");
						}else if(discount % 10 == 0) {
							result.setCoupon_discount(discount / 10 + "折");
						}else {
							result.setCoupon_discount(discountBd.divide(new BigDecimal("10")).setScale(1).toString() + "折");
						}
						//计算优惠金额:
						couponAmount = new BigDecimal(100-discount).multiply(amount).divide(new BigDecimal("100")).setScale(2, RoundingMode.HALF_UP);
						result.setCoupon_amount("减" + couponAmount.toString());
						payAmount = amount.subtract(couponAmount).setScale(2, RoundingMode.HALF_UP);
					}else {
						payAmount = new BigDecimal("0.00");
					}
				}
			}
		}
		result.setPay_amount(payAmount.setScale(2).toString());
		
		//计算额外金额
		BigDecimal sub = payAmount.subtract(cash_amount);
		if(sub.compareTo(new BigDecimal("0.00")) > 0) {
			result.setExtra_amount(sub.setScale(2).toString());
		}else {
			result.setExtra_amount("0.00");
		}
		return result;
	}

	@Override
	public PaymentVIPCardResultDTO paymentVIPCard(PaymentVIPCardDTO paymentVIPCard) throws BizException {
		
		PaymentVIPCardResultDTO  resultDTO = new PaymentVIPCardResultDTO();
		UserChargeLogDO userChargeLogDO = new UserChargeLogDO();
		Long userId = paymentVIPCard.getUserId();
		userChargeLogDO.setChannel(BizConstants.CHARGE_LOG_CHANNEL_1);
		userChargeLogDO.setUserId(paymentVIPCard.getUserId());
		userChargeLogDO.setCouponId(paymentVIPCard.getCoupon_id());
		userChargeLogDO.setChargeType(1);
		userChargeLogDO.setVipType(paymentVIPCard.getVip_type());
		userChargeLogDO.setCreateTime(new Date());
		userChargeLogDO.setTradeStatus(BizConstants.USER_CHARGE_STATUS_0);  //初始化
		String outTradeNo = weChatUtilManager.getRandomNumber();
		userChargeLogDO.setOutTradeNo(outTradeNo);
		
		String isTest = configInfoManager.getValue("is_test");
		//1.判断额外缴费金额是否是0
		BigDecimal extraAmount = new BigDecimal(paymentVIPCard.getExtra_amount());
		BigDecimal payAmount = new BigDecimal(paymentVIPCard.getPay_amount());
		
		//如果 extra_amount 为0时，说明不进行微信支付就可以完成月卡的购买
		if(new BigDecimal("0.00").compareTo(extraAmount) == 0) {	
			userChargeLogDO.setChargeAmount(extraAmount);
			userChargeLogDO.setExAmount(extraAmount);
			//支付的余额大小
			BigDecimal ac = payAmount;
			userChargeLogDO.setAcAmount(ac.multiply(new BigDecimal("100")).intValue());//余额支付大小
			userChargeLogDO.setTradeStatus(BizConstants.USER_CHARGE_STATUS_2);
			userChargeLogDO.setModifyTime(new Date());
			userChargeLogDAO.insert(userChargeLogDO);
			//修改用户余额信息
			AccountCashDTO acDTO = new AccountCashDTO();
			acDTO.setUserId(userId);
			acDTO.setChangeAmount(ac);
			acDTO.setOperType(BizConstants.ACCOUNT_CASH_OPER_TYPE_20);
			acDTO.setChargeType(BizConstants.ACCOUNT_CASH_CHARGE_TYPE_51);
			acDTO.setOrderId(userChargeLogDO.getId());
			accountCashService.updateAccountCash(acDTO);
			
			//增加月卡
			VipMemberLogDTO vipMemberLogDTO = new VipMemberLogDTO();
			vipMemberLogDTO.setChargeType(10);
			vipMemberLogDTO.setUserId(userId);
			vipMemberLogDTO.setVipType(paymentVIPCard.getVip_type());
			vipMemberService.saveVipMember(vipMemberLogDTO);
			//保存用户扣费标准信息
			UserCostFlagDTO ucfDTO = new UserCostFlagDTO();
			ucfDTO.setUserId(userId);
			if(1 == paymentVIPCard.getVip_type()) {
				ucfDTO.setFlag(3);
			}else {
				ucfDTO.setFlag(4);
			}
			ucfDTO.setPrice(new BigDecimal("0.00"));
			ucfDTO.setRemainder(payAmount);
			userCostFlagService.saveUserCostFlag(ucfDTO);
			
			//FIXME 修改优惠券信息
			if(!ObjectUtils.isEmpty(paymentVIPCard.getCoupon_id())) {
				couponService.updateCoupon(paymentVIPCard.getCoupon_id(), BizConstants.COUPON_EVENT_USED, userChargeLogDO.getId());
			}
			resultDTO.setPayFlag(0);	//不需要调用微信支付
		}else{
			//支付的余额大小
			BigDecimal ac = payAmount.subtract(extraAmount);
			userChargeLogDO.setAcAmount(ac.multiply(new BigDecimal("100")).intValue());
			userChargeLogDO.setChargeAmount(extraAmount);
			if("1".equals(isTest)) {
				userChargeLogDO.setChargeAmount(new BigDecimal("0.01"));
			}
			userChargeLogDO.setExAmount(extraAmount);
			userChargeLogDAO.insert(userChargeLogDO);
			String total_fee = (int)(userChargeLogDO.getChargeAmount().doubleValue()*100) +"";
		    String wxAppId = configInfoManager.getValue("wxapp.appid");
		    String mch_id =  configInfoManager.getValue("wxapp.merchant_id");
		    String notifyUrl = configInfoManager.getValue("wxapp.notify_url");
		    String merchant_key = configInfoManager.getValue("wxapp.merchant_key");
		    
		    //获取OPENID 
		    WxUserRelationDO condition = new WxUserRelationDO();
		    condition.setUserId(userId);
		    condition.setAppId(wxAppId);
		    List<WxUserRelationDO> list = wxUserRelationDAO.listByCondition(condition);
		    if(CollectionUtils.isEmpty(list)) {
		    		logger.error("根据userid[{}], appid[{}]获取不到openid", userId, wxAppId);
		    		throw new BizException(RspCodeEnum.WX_OPENID_NOT_FOUND);
		    }
		    String openId = list.get(0).getOpenid();
		    String prepayId = payment("微信小程序-支付", outTradeNo, openId, total_fee, wxAppId, mch_id, notifyUrl, merchant_key, paymentVIPCard.getIp());
		    logger.info("openid:{},统一下单返回:{}",openId, prepayId);
		    
		    SortedMap<Object, Object> signParams = new TreeMap<Object, Object>();
		    String timeStamp = PayCommonUtil.create_timestamp();
		    String nonceStr = PayCommonUtil.create_nonce_str();
		    signParams.put("appId", wxAppId);
		    signParams.put("nonceStr", nonceStr);
		    signParams.put("package", "prepay_id=" + prepayId);
		    signParams.put("timeStamp", timeStamp);
		    signParams.put("signType", "MD5");
		    // 生成支付签名，要采用URLENCODER的原始值进行MD5算法！
		    String sign = PayCommonUtil.createSign(signParams, merchant_key);
		    resultDTO.setAppId(wxAppId);
		    resultDTO.setNonceStr(nonceStr);
		    resultDTO.setPkg("prepay_id=" + prepayId);
		    resultDTO.setPrepayId(prepayId);
		    resultDTO.setSign(sign);
		    resultDTO.setSignType("MD5");
		    resultDTO.setTimeStamp(timeStamp);
		    if(!ObjectUtils.isEmpty(paymentVIPCard.getCoupon_id())) {
				couponService.updateCoupon(paymentVIPCard.getCoupon_id(), BizConstants.COUPON_EVENT_LOCK, userChargeLogDO.getId());
			}
			resultDTO.setPayFlag(1);
		}
		
		return resultDTO;
	}

	@Override
	public RefundPyStatusDTO refundSubmit(UserRefundDTO userRefund) throws BizException {
		RefundPyStatusDTO refundPyStatusDTO = refund(userRefund.getUserid());
		//保存退款信息
		UserChargeLogDO chargeLog = userChargeLogDAO.getDepositByUserId(userRefund.getUserid());
		Long chargeId = chargeLog.getId();
		
		UserRefundInfoDO userRefundInfo = new UserRefundInfoDO();
		userRefundInfo.setMemo(userRefund.getMemo());
		userRefundInfo.setRefundReason(userRefund.getRefundReason());
		userRefundInfo.setUserChargeLogId(chargeId);
		userRefundInfo.setUserId(userRefund.getUserid());
		userRefundInfo.setCreateTime(new Date());
		userRefundInfoDAO.insert(userRefundInfo);
		return refundPyStatusDTO;
	}

	public Long getUseridByWxToken(String usertoken) {
		logger.info("getUseridByWxToken usertoken{}",usertoken);
		UserTokenDO userTokenDO = userTokenDAO.selectUseridByWxToken(usertoken);
		if(userTokenDO != null && userTokenDO.getUserId() != null) {
			return userTokenDO.getUserId();
		}else {
			return null;
		}
	}

	@Override
	public List<ChargeAmountDTO> getChargeAmountListV2(Long userid) throws BizException {
		List<ChargeAmountDTO> list = new ArrayList<ChargeAmountDTO>();
		list.add(new ChargeAmountDTO("100", configInfoManager.getValue("100")));
		list.add(new ChargeAmountDTO("50", configInfoManager.getValue("50")));
		list.add(new ChargeAmountDTO("30", configInfoManager.getValue("30")));
		list.add(new ChargeAmountDTO("10", configInfoManager.getValue("10")));
		for(ChargeAmountDTO chargeAmountDTO : list) {
			String chargeCode = chargeAmountDTO.getCharge_code();
			CouponInfo couponInfo = couponService.getCoupon("0", userid, chargeCode);
			BigDecimal payAmount = null ;
			if(null != couponInfo) {
				chargeAmountDTO.setCoupon_id(couponInfo.getCoupon_id());
				chargeAmountDTO.setCoupon_type(couponInfo.getCoupon_desc());
				if("1".equals(couponInfo.getCoupon_type())) { //满减券
					chargeAmountDTO.setCoupon_discount("满" + couponInfo.getCoupon_condition()+"元减"+couponInfo.getCoupon_cash()+"元");
					payAmount = new BigDecimal(chargeCode).subtract(new BigDecimal(couponInfo.getCoupon_cash()));
					chargeAmountDTO.setCoupon_amount("-"+couponInfo.getCoupon_cash());
				}else {	//满赠券
					chargeAmountDTO.setCoupon_discount("满" + couponInfo.getCoupon_condition()+"元赠"+couponInfo.getCoupon_cash()+"元");
					payAmount = new BigDecimal(chargeCode);
					chargeAmountDTO.setCoupon_amount("+"+couponInfo.getCoupon_cash());
				}
				chargeAmountDTO.setPay_amount(payAmount.setScale(2).toString());
			}
		}
		return list;
	}

	@Override
	public PaymentVIPCardResultDTO paymentChargeAmount(PaymentChargeAmountDTO pcaDTO) throws BizException {
		UserChargeLogDO userChargeLogDO = new UserChargeLogDO();
		Long userId = pcaDTO.getUserid();
		userChargeLogDO.setChannel(BizConstants.CHARGE_LOG_CHANNEL_1);
		userChargeLogDO.setUserId(userId);
		userChargeLogDO.setCouponId(pcaDTO.getCoupon_id());
		userChargeLogDO.setChargeType(pcaDTO.getCharge_type());
		userChargeLogDO.setVipType(0);
		userChargeLogDO.setCreateTime(new Date());
		userChargeLogDO.setTradeStatus(BizConstants.USER_CHARGE_STATUS_0);  //初始化
		String outTradeNo = weChatUtilManager.getRandomNumber();
		userChargeLogDO.setOutTradeNo(outTradeNo);
		
		BigDecimal chargeAmount = new BigDecimal(pcaDTO.getCharge_code());
		BigDecimal payAmount = chargeAmount;
		BigDecimal exAmount = chargeAmount;
		if(!ObjectUtils.isEmpty(pcaDTO.getPay_amount())) {
			payAmount = new BigDecimal(pcaDTO.getPay_amount());
			exAmount = new BigDecimal(pcaDTO.getPay_amount());
		}
		userChargeLogDO.setAcAmount(0);
		//新增orderTransId
		if(null != pcaDTO.getOrderTransId()) {
			userChargeLogDO.setOrderTransId(pcaDTO.getOrderTransId());
			if(ObjectUtils.isEmpty(pcaDTO.getCoupon_id())) {
				BigDecimal ac = chargeAmount.subtract(payAmount).setScale(2);
				userChargeLogDO.setAcAmount(ac.multiply(new BigDecimal("100")).intValue());
			}
		}
		
				
		if(new BigDecimal("0.00").compareTo(exAmount) == 0) {
			userChargeLogDO.setExAmount(exAmount);
			userChargeLogDO.setChargeAmount(payAmount);
			userChargeLogDO.setTradeStatus(BizConstants.USER_CHARGE_STATUS_2);
			userChargeLogDO.setModifyTime(new Date());
			userChargeLogDAO.insert(userChargeLogDO);
			
			saveChargeInfo(userChargeLogDO);
						
			PaymentVIPCardResultDTO dto = new PaymentVIPCardResultDTO();
			dto.setPayFlag(0);	//不需要调用微信支付
			return dto;
		}
		
		String isTest = configInfoManager.getValue("is_test");
		if("1".equals(isTest)) {
			payAmount = new BigDecimal("0.01");
		}
		logger.info("当前实际充值金额为\t"+payAmount.toString());
		userChargeLogDO.setExAmount(exAmount);
		userChargeLogDO.setChargeAmount(payAmount);
		userChargeLogDAO.insert(userChargeLogDO);
		String total_fee = (int)(payAmount.doubleValue()*100) +"";
		String wxAppId = configInfoManager.getValue("wxapp.appid");
		String mch_id =  configInfoManager.getValue("wxapp.merchant_id");
		String notifyUrl = configInfoManager.getValue("wxapp.notify_url");
		String merchant_key = configInfoManager.getValue("wxapp.merchant_key");
		
		//获取OPENID 
		String openid = wxUserRelationDAO.getOpenIdByUser(userId);
		String prepayId = payment("微信小程序-支付", outTradeNo, openid, total_fee, wxAppId, mch_id, notifyUrl, merchant_key, pcaDTO.getIp());
		logger.info("openid:{},统一下单返回:{}",openid,prepayId);
		
		SortedMap<Object, Object> signParams = new TreeMap<Object, Object>();
		String timeStamp = PayCommonUtil.create_timestamp();
		String nonceStr = PayCommonUtil.create_nonce_str();
		signParams.put("appId", wxAppId);
		signParams.put("nonceStr", nonceStr);
		signParams.put("package", "prepay_id=" + prepayId);
		signParams.put("timeStamp", timeStamp);
		signParams.put("signType", "MD5");
		// 生成支付签名，要采用URLENCODER的原始值进行MD5算法！
		String sign = PayCommonUtil.createSign(signParams, merchant_key);
		PaymentVIPCardResultDTO dto = new PaymentVIPCardResultDTO();
		dto.setAppId(wxAppId);
		dto.setNonceStr(nonceStr);
		dto.setPkg("prepay_id=" + prepayId);
		dto.setPrepayId(prepayId);
		dto.setSign(sign);
		dto.setSignType("MD5");
		dto.setTimeStamp(timeStamp);
		dto.setPayFlag(1);
		if(!ObjectUtils.isEmpty(pcaDTO.getCoupon_id())) {
			couponService.updateCoupon(pcaDTO.getCoupon_id(), BizConstants.COUPON_EVENT_LOCK, userChargeLogDO.getId());
		}
		return dto;
	}
	
	public void updateWxUserInfoById(WxUserRelationDTO dto) {
		logger.info("updateWxUserInfoById {},begin",dto.getId());
		WxUserRelationDO updateData = new WxUserRelationDO();
		BeanUtils.copyProperties(dto,updateData);
		wxUserRelationDAO.updateById(updateData);
		logger.info("updateWxUserInfoById {},end",dto.getId());

	}

	@Override
	public void cancelPayment(Long userid) throws BizException {
		UserChargeLogDO userChargeLog = userChargeLogDAO.getByUserId(userid);
		if(null == userChargeLog) {
			throw new BizException(RspCodeEnum.OBJ_NOT_FOUND.setRspMessage("userChargeLog"));
		}
		Integer status = userChargeLog.getTradeStatus();
		if(0 == status || 1 == status) {
			//取消支付或者支付失败
			String couponId = userChargeLog.getCouponId();
			if(!ObjectUtils.isEmpty(couponId)) {
				couponService.updateCoupon(couponId, BizConstants.COUPON_EVENT_TOOK, null);
			}
			userChargeLog.setTradeStatus(BizConstants.USER_CHARGE_STATUS_4);
			userChargeLog.setModifyTime(new Date());
			userChargeLogDAO.update(userChargeLog);
		}
	}
	
	@Autowired
	private BookInfoDAO bookInfoDAO;
	
	@Override
	public PrepareBuyBookResDTO prepareBuyBook(PrepareBuyBookReqDTO prepareBuyBookReq) throws BizException{
		
		//判断是否可以购买图书
		Integer flag = Integer.valueOf(configInfoManager.getValue("buy_book_switch"));
		if(0 == flag) {
			throw new BizException(RspCodeEnum.BUY_BOOK_NOT_USED);
		}
		PrepareBuyBookResDTO resDTO = new PrepareBuyBookResDTO();
		
		Long userId = prepareBuyBookReq.getUserid();
		Long orderTransId = prepareBuyBookReq.getOrderTransId();
		String isbn = prepareBuyBookReq.getIsbn();
		
		//1.查找图书单价以及图书名称
		BookInfoDO bookInfo = bookInfoDAO.get(isbn);
		resDTO.setBookname(bookInfo.getBookName());
		resDTO.setDiscount_price(bookInfo.getPrice().multiply(new BigDecimal("0.7")).setScale(2, RoundingMode.HALF_UP).toString());
		//2.查找用户借阅费用
		OrderTransDO orderTransDO = orderTransDAO.get(orderTransId);
		BigDecimal transAmount = orderTransDO.getTransAmount();
		
		resDTO.setBookcaseId(orderTransDO.getShelfCode());
		if(null == transAmount) {
			transAmount = new BigDecimal("0.00");
		}
		resDTO.setTrans_amount(transAmount.setScale(2).toString());
		resDTO.setPay_amount(new BigDecimal(resDTO.getDiscount_price()).subtract(transAmount).setScale(2).toString());
		if(new BigDecimal("0.00").compareTo(new BigDecimal(resDTO.getPay_amount())) > 0) {
			resDTO.setPay_amount("0.00");
		}
		BigDecimal cashAmount = accountCashDAO.getByUserid(userId).getCashAmount();
		if(cashAmount.compareTo(new BigDecimal("0.00")) <= 0) {
			resDTO.setCash_amount("0.00");
			resDTO.setExtra_amount(resDTO.getPay_amount());
		}else {
			resDTO.setCash_amount(cashAmount.setScale(2).toString());
			BigDecimal extraAmount = new BigDecimal(resDTO.getPay_amount()).subtract(cashAmount);
			if(extraAmount.compareTo(new BigDecimal("0.00")) <= 0) {
				resDTO.setExtra_amount("0.00");
			}else {
				resDTO.setExtra_amount(extraAmount.setScale(2).toString());
			}
		}
		
		
		//查找用户的coupon
		CouponInfo couponInfo = couponService.getCoupon("3", userId, orderTransDO.getShelfCode());
		if(null != couponInfo) {
			resDTO.setCoupon_id(couponInfo.getCoupon_id());
			resDTO.setExtra_amount("0.00");
		}
		
		return resDTO;
	}

}
